#pragma once

#include "Action.h"

#include "ActivityNode.h"
#include "Behavior.h"
#include "Classifier.h"
#include "Constraint.h"
#include "InputPin.h"
#include "OutputPin.h"

namespace uml {

const bool Action::isLocallyReentrant_default_ = false;
Action::Action(const QString& umlType)
    : ExecutableNode(umlType) {}

void Action::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    ExecutableNode::fromJson(json, errorList);
    context_ = JsonSerializable::create<Classifier>(json.value("context"), errorList);

    JsonSerializable::fromJsonArray(inputs_, "inputs", json, errorList);
    isLocallyReentrant_ = json.value("isLocallyReentrant").toBool(isLocallyReentrant_default_);
    JsonSerializable::fromJsonArray(localPostconditions_, "localPostconditions", json, errorList);
    JsonSerializable::fromJsonArray(localPreconditions_, "localPreconditions", json, errorList);
    JsonSerializable::fromJsonArray(outputs_, "outputs", json, errorList);
}

void Action::toJson(QJsonObject& json) {
    ExecutableNode::toJson(json);
    if (context_) {
        QJsonObject context_json;
        context_->toJson(context_json);
        json.insert("context", context_json);
    }
    JsonSerializable::toJsonArray(inputs_, "inputs", json);
    if (isLocallyReentrant_ != isLocallyReentrant_default_) {
        json.insert("isLocallyReentrant", isLocallyReentrant_);
    }
    JsonSerializable::toJsonArray(localPostconditions_, "localPostconditions", json);
    JsonSerializable::toJsonArray(localPreconditions_, "localPreconditions", json);
    JsonSerializable::toJsonArray(outputs_, "outputs", json);
}

/// <summary>
/// allActions
    /// Return this Action and all Actions contained directly or indirectly in it. By
    /// default only the Action itself is returned, but the operation is overridden for
    /// StructuredActivityNodes.
/// </summary>
    /// <code>
    /// result = (self->asSet())
    /// </code>
shared_ptr<vector<Action>> Action::allActions() const
{
    return nullptr;
}

/// <summary>
/// allOwnedNodes
    /// Returns all the ActivityNodes directly or indirectly owned by this Action. This
    /// includes at least all the Pins of the Action.
/// </summary>
    /// <code>
    /// result = (input.oclAsType(Pin)->asSet()->union(output->asSet()))
    /// </code>
shared_ptr<vector<ActivityNode>> Action::allOwnedNodes() const
{
    return nullptr;
}

/// <summary>
/// containingBehavior
/// </summary>
    /// <code>
    /// result = (if inStructuredNode<>null then inStructuredNode.containingBehavior() 
    /// else if activity<>null then activity
    /// else interaction 
    /// endif
    /// endif
    /// )
    /// </code>
shared_ptr<Behavior> Action::containingBehavior() const
{
    return nullptr;
}

/// <summary>
/// context getter
/// The context Classifier of the Behavior that contains this Action, or the
/// Behavior itself if it has no context.
/// </summary>
shared_ptr<Classifier> Action::context() const {
    return context_;
}

/// <summary>
/// context setter
/// The context Classifier of the Behavior that contains this Action, or the
/// Behavior itself if it has no context.
/// </summary>
void Action::setContext(shared_ptr<Classifier> value) {
    context_ = value;
}

/// <summary>
/// inputs getter
/// The ordered set of InputPins representing the inputs to the Action.
/// </summary>
vector<shared_ptr<InputPin>>& Action::inputs() {
    return inputs_;
}

/// <summary>
/// isLocallyReentrant getter
/// If true, the Action can begin a new, concurrent execution, even if there is
/// already another execution of the Action ongoing. If false, the Action cannot
/// begin a new execution until any previous execution has completed.
/// </summary>
bool Action::isLocallyReentrant() const {
    return isLocallyReentrant_;
}

/// <summary>
/// isLocallyReentrant setter
/// If true, the Action can begin a new, concurrent execution, even if there is
/// already another execution of the Action ongoing. If false, the Action cannot
/// begin a new execution until any previous execution has completed.
/// </summary>
void Action::setIsLocallyReentrant(bool value) {
    isLocallyReentrant_ = value;
}

/// <summary>
/// localPostconditions getter
/// A Constraint that must be satisfied when execution of the Action is completed.
/// </summary>
vector<shared_ptr<Constraint>>& Action::localPostconditions() {
    return localPostconditions_;
}

/// <summary>
/// localPreconditions getter
/// A Constraint that must be satisfied when execution of the Action is started.
/// </summary>
vector<shared_ptr<Constraint>>& Action::localPreconditions() {
    return localPreconditions_;
}

/// <summary>
/// outputs getter
/// The ordered set of OutputPins representing outputs from the Action.
/// </summary>
vector<shared_ptr<OutputPin>>& Action::outputs() {
    return outputs_;
}

} // namespace uml
